﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
using System;
using System.Net;
using System.IO;
using System.Runtime.Serialization;
using System.Threading;
using System.ComponentModel;
using System.Collections;
using BrainTechLLC.Communication;
using System.Collections.Generic;
using BrainTechLLC.ThreadSafeObjects;
using AltSerialize;
using System.Reflection;
#if NO_SILVERLIGHT
using BrainTechLLC.Logging;
using System.Text;
using Mud.EmlenMudMain;
using System.Diagnostics;
#endif
#if USE_HYPER
using Hyper.ComponentModel;
#endif

namespace BrainTechLLC
{
    [Serializable]
    [DataContract]
    public static class Globals
    {
#if NO_SILVERLIGHT
        public static FileLogger InGameLog;
#endif
        public readonly static CombatHandler Combat = new CombatHandler();
        public readonly static TimeFlow TimeFlow = new TimeFlow();
        public static SchedulingEngine SchedulingEngine = new SchedulingEngine(8);
        public static readonly InfluenceManager InfluenceManager = new InfluenceManager();
        public static bool Initialized;
        public readonly static object LockObject = new object();
        public static IncomingMessageHandler IncomingHandler = new IncomingMessageHandler();
        public static CommunicationsServer Server = new CommunicationsServer(IPAddress.Any, 4502, IncomingHandler);

        static Globals()
        {
            if (Server != null)
                Server.WantExit = true;
        }

        public static void Shutdown()
        {
            WorldMap.Instance.Save(new List<object>());
            SchedulingEngine.WantExit = true;
            Server.ShutdownServer();
        }

        public static void CreateTestWorld()
        {
            int maxX = 40;
            int maxY = 40;
            Random r = new Random();

            for (int x = 0; x < maxX; x++)
            {
                for (int y = 0; y < maxY; y++)
                {
                    GameLocation loc = new GameLocation()
                    {
                        XYZ = new LocationInt(x, y, 1),
                    };
                    loc.Register();
                    WorldMap.Instance.World.AddTerminatingItem(loc, new int[] { x, y, 1 });
                }
            }

            for (int x = 0; x < maxX; x++)
            {
                for (int y = 0; y < maxY; y++)
                {
                    GameLocation loc = WorldMap.Instance.World[x, y, 1];

                    if (x > 0)
                    {
                        LocationEdge edge = new LocationEdge()
                        {
                            Direction = GeneralDirection.W,
                            ToLocationId = WorldMap.Instance.World[x - 1, y, 1].AssociatedID
                        };
                        edge.Register();
                        loc.EdgeIDs[(int)GeneralDirection.W] = edge.AssociatedID;
                    }
                    if (x < maxX - 1)
                    {
                        LocationEdge edge = new LocationEdge()
                        {
                            Direction = GeneralDirection.E,
                            ToLocationId = WorldMap.Instance.World[x + 1, y, 1].AssociatedID
                        };
                        edge.Register();
                        loc.EdgeIDs[(int)GeneralDirection.E] = edge.AssociatedID;
                    }
                    if (y > 0)
                    {
                        LocationEdge edge = new LocationEdge()
                        {
                            Direction = GeneralDirection.N,
                            ToLocationId = WorldMap.Instance.World[x, y - 1, 1].AssociatedID
                        };
                        edge.Register();
                        loc.EdgeIDs[(int)GeneralDirection.N] = edge.AssociatedID;
                    }
                    if (y < maxY - 1)
                    {
                        LocationEdge edge = new LocationEdge()
                        {
                            Direction = GeneralDirection.S,
                            ToLocationId = WorldMap.Instance.World[x, y + 1, 1].AssociatedID
                        };
                        edge.Register();
                        loc.EdgeIDs[(int)GeneralDirection.S] = edge.AssociatedID;
                    }
                }
            }

            WorldMap.Instance.PerformPostRestoreSetup();

            Template bodyTemplate = new Template()
            {
                TypeName = "BodyAbility",
                FriendlyName = "BodyTemplate",
                PropertiesToSet = new PropertyData(new IdentifierAndValue("AbilityName", "Body"))
            };
            bodyTemplate.Register();

            Template legsTemplate = new Template()
            {
                TypeName = "LegsAbility",
                FriendlyName = "LegsTemplate",
                PropertiesToSet = new PropertyData(new IdentifierAndValue("AbilityName", "Legs"))
            };
            legsTemplate.Register();

            Template eyesTemplate = new Template()
            {
                TypeName = "EyesAbility",
                FriendlyName = "EyesTemplate",
                PropertiesToSet = new PropertyData(new IdentifierAndValue("AbilityName", "Eyes"))
            };
            eyesTemplate.Register();

            Template charTemplate = new GameCharTemplate() { TypeName = "GameChar", FriendlyName = "GameCharTemplate" };
            charTemplate.Register();

            GameChar c1 = charTemplate.CreateInstance<GameChar>(null);
            c1.LocationInt = new LocationInt(2, 2, 1);
            c1.Name.Name = "Owen";
            c1.Name.Keywords = "char1~owen~testing1";
            c1.PlaceInWorld(null);

            GameChar c2 = charTemplate.CreateInstance<GameChar>(null);
            c2.LocationInt = new LocationInt(2, 2, 1);
            c2.Name.Name = "Fred";
            c2.Name.Keywords = "char2~joshua~testing2";
            c2.PlaceInWorld(null);

            for (int n = 0; n < 200; n++)
            {
                GameChar cc = charTemplate.CreateInstance<GameChar>(null);
                cc.LocationInt = new LocationInt(r.Next(1, 39), r.Next(1, 39), 1);
                cc.Name = new NameAndDescription()
                {
                    Keywords = "test~short~desc",
                    Name = "test",
                    ShortDescription = "short desc"
                };
                cc.PlaceInWorld(null);

                State state2 = StateFactory.CreateFatigueState(-2);

                if (cc.States.FindStateByName(state2.StateName) == null)
                    cc.States.AddState(state2, 0);
            }

            WorldMap.Instance.MarkChanged();
        }

        public static void Test()
        {
            Server.ListenOnLocalIP = IPAddress.Any;
            Server.ListenPort = 4443;
            Server.IDToControlReceiverMap = new MapIDToControlReceiver();
            Server.IncomingMessageHandler = new IncomingMessageHandler();
            Server.BeginListening();
        }

        public static bool CheckInitialized()
        {
            if (!Initialized)
            {
                lock (LockObject)
                {
                    if (!Initialized)
                    {
#if NO_SILVERLIGHT
                        Globals.InGameLog = new FileLogger("c:\\InGameLog");
                        Globals.InGameLog.BeginLogging();
#else 
                        Notification.RegisterMessageSerializationTypes();
#endif
                        SchedulingEngine.StartSchedulingEngine();
                        Initialized = true;
                        TypeProvider.GetInstance();
#if NO_SILVERLIGHT
                        AOP.EnableAOP(MockMode.None);
                        FileLogger fileLogger = new FileLogger("Log_" + DateTime.Now.ToShortDateString().Replace("/", "_"));
                        GlobalLogger.RegisterLogger(fileLogger);
                        GlobalLogger.Logger.BeginLogging();
#endif
                        ConnectionPoints.GetInstance().Initialize();
                        Combat.Initialize();
                        return true;
                    }
                }
            }
            return false;
        }
    }
}